/*
 * 2007/05
 * 2007/10
 * 2011/11/17 - 13:32
 */
package org.nettyflux.example.asteroids;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.util.Arrays;
import java.util.List;
import javax.swing.JPanel;

/**
 * @author Victor Williams Stafusa da Silva
 */
public class RenderScreen extends JPanel {
    private static final long serialVersionUID = 7248749848875047263L;

    private final Thread controlThread;
    private Image doublebuffer;
    private Ball ball1;
    private Ball ball2;
    private Paddle paddle;
    private int lifes;
    private int points;
    private int level;
    private final int renderWidth;
    private final int renderHeight;
    private volatile boolean closed;
    private long lastTickTime = 0;

    public RenderScreen(int width, int height) {
        this.setLayout(null);
        this.setBorder(null);
        this.closed = false;
        this.renderWidth = width;
        this.renderHeight = height;
        this.doublebuffer = createImage(width, height);
        lifes = 50;
        points = 0;
        level = 1;
        paddle = new Paddle(9 * width / 10, (height - Paddle.HEIGHT) / 2, this);
        ball1 = new Ball(30, 30, this, paddle);
        ball2 = new Ball(30, 90, this, paddle);
        controlThread = new Thread() {
            @Override
            public void run() {
                while (!closed) {
                    try {
                        Thread.sleep(10);
                        move();
                        repaint();
                    } catch (InterruptedException e) {
                    }
                }
            }
        };
    }

    public List<ScreenObject> getScreenObjects() {
        return Arrays.asList(paddle, ball1, ball2);
    }

    private void move() {
        double deltaT = markTick();
        for (ScreenObject obj : getScreenObjects()) {
            obj.move(deltaT);
        }
    }

    private double markTick() {
        long t = System.currentTimeMillis();
        double deltaT = (lastTickTime == 0 ? 0 : (t - lastTickTime));
        deltaT /= 1000;
        lastTickTime = t;
        return deltaT;
    }

    public void initSize() {
        this.setSize(renderWidth, renderHeight);
    }

    public void start() {
        controlThread.start();
    }

    @Override
    public void paintComponent(Graphics screen) {
        if (doublebuffer == null) doublebuffer = createImage(renderWidth, renderHeight);
        Graphics2D g = (Graphics2D) doublebuffer.getGraphics();

        drawGraphics(g);

        g.dispose();
        screen.drawImage(doublebuffer, 0, 0, this);
    }

    private void drawGraphics(Graphics2D g) {
        g.clearRect(0, 0, getWidth(), getHeight());
        g.setColor(Color.BLACK);
        g.drawRect(0, 0, renderWidth - 1, renderHeight - 1);
        if (lifes > 0) {
            for (ScreenObject obj : getScreenObjects()) {
                obj.draw(g);
            }
        } else {
            g.drawString("Soory, you lose!", renderWidth / 2 - 40, renderHeight / 2 - 5);
        }
        g.setColor(Color.RED);
        g.drawString("Lifes: " + lifes, 5, 15);
        g.drawString("Points: " + points, 5, 30);
        g.drawString("Level: " + level, 5, renderHeight - 15);
        g.drawString("Speed: " + ((double) ((int) (ball1.getSpeed() * 1000))) / 1000.0, 5, renderHeight - 30);
    }

    public void paddleGoUp(boolean b) {
        paddle.setGoingUpKey(b);
    }

    public void paddleGoDown(boolean b) {
        paddle.setGoingDownKey(b);
    }

    public boolean markPoint() {
        points++;
        if (points % 10 == 0) {
            level++;
            return true;
        }
        return false;
    }

    public void decreaseLifes() {
        lifes--;
        if (lifes == 0) {
            close();
        }
    }

    public void close() {
        closed = true;
    }

    public int getRenderWidth() {
        return renderWidth;
    }

    public int getRenderHeight() {
        return renderHeight;
    }
}